 package com.easysoft.framework.quartz.scheduling;

import java.util.ArrayList;
import java.util.List;

import org.quartz.JobDetail;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;

import com.easysoft.framework.annotation.quartz.CronQuartzJob;
import com.easysoft.framework.annotation.quartz.SimpleQuartzJob;

/**
 * 根据注解自动加载任务
 * 
 * @author try
 */
public class AutoSchedulerFactoryBean extends SchedulerFactoryBean {

	private static final Logger logger = LoggerFactory.getLogger(AutoSchedulerFactoryBean.class);

	private ApplicationContext applicationContext;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
		super.setApplicationContext(applicationContext);
	}

	@Override
	public void registerJobsAndTriggers() throws SchedulerException {

		List<Trigger> triggerList = new ArrayList<Trigger>();
		List<JobDetail> jobDetailList = new ArrayList<JobDetail>();

		int space = 3333; // 为了防止多个轮询任务启动的时候间隔太近，所以设置一个3秒的间隔
		int count = 0;

		try {
			// 获取所有bean name
			String[] beanNames = applicationContext.getBeanNamesForType(AbstractJob.class);

			for (String beanName : beanNames) {

				logger.info("-------------------------------------read bean {}-------------------------------------", beanName);

				Class<?> targetClass = applicationContext.getType(beanName);

				// 循环判断是否标记了QuartzJob注解
				if (targetClass.isAnnotationPresent(CronQuartzJob.class)) {
					CronQuartzJob triggerType = targetClass.getAnnotation(CronQuartzJob.class);

					// 注册定时器业务类
					JobDetailFactoryBean jobDetail = new JobDetailFactoryBean();
					jobDetail.setBeanName(beanName);
					jobDetail.setJobClass(targetClass);
					jobDetail.setDurability(true);
					jobDetail.setRequestsRecovery(true);
					jobDetail.afterPropertiesSet();

					CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
					trigger.setBeanName(beanName + "CronBean");
					trigger.setJobDetail(jobDetail.getObject());
					trigger.setCronExpression(triggerType.cronExpression()); // 获取时间表达式
					trigger.afterPropertiesSet();

					triggerList.add(trigger.getObject());

					logger.info("-------------------------------------load job {}-------------------------------------", beanName);
				}
				else if (targetClass.isAnnotationPresent(SimpleQuartzJob.class)) {
					SimpleQuartzJob triggerType = targetClass.getAnnotation(SimpleQuartzJob.class);

					JobDetailFactoryBean jobDetail = new JobDetailFactoryBean();
					jobDetail.setBeanName(beanName);
					jobDetail.setJobClass(targetClass);
					jobDetail.setDurability(true);
					jobDetail.setRequestsRecovery(true);
					jobDetail.afterPropertiesSet();

					jobDetailList.add(jobDetail.getObject());

					SimpleTriggerFactoryBean trigger = new SimpleTriggerFactoryBean();
					trigger.setBeanName(beanName + "SimpleBean");
					trigger.setJobDetail(jobDetail.getObject());
					trigger.setRepeatInterval(triggerType.repeatInterval());
					trigger.setStartDelay(triggerType.startDelay() + count * space);
					trigger.setRepeatCount(triggerType.repeatCount());
					trigger.afterPropertiesSet();

					triggerList.add(trigger.getObject());

					logger.info("-------------------------------------load job {}-------------------------------------", beanName);
					
					count ++;
				}
			}
		}
		catch (Exception | Error e) {
			logger.error(e.getMessage());
		}

		Trigger[] triggers = triggerList.toArray(new Trigger[triggerList.size()]);
		JobDetail[] jobDetails = jobDetailList.toArray(new JobDetail[jobDetailList.size()]);

		super.setJobDetails(jobDetails);
		super.setTriggers(triggers);
		super.registerJobsAndTriggers();
	}

}
